package com.king.pattem.proxy.dynamic;

import net.sf.cglib.proxy.Enhancer;

import java.lang.reflect.Proxy;

import com.king.pattem.proxy.statics.DBQuery;
import com.king.pattem.proxy.statics.IDBQuery;

import javassist.*;
import javassist.util.proxy.ProxyFactory;
import javassist.util.proxy.ProxyObject;

/**
 * @author taomk
 * @version 1.0
 * @since 15-1-16 下午10:11
 */
public class Main {
	public static void main(String[] args) throws Exception {
		// JDK 动态代理
		IDBQuery jdkProxy = (IDBQuery) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{IDBQuery.class}, new JdkDbQueryHandler());
		System.out.println(jdkProxy.request());

		// CGLIB 动态代理
		Enhancer enhancer = new Enhancer();
		// 指定切入器，定义代理类逻辑
		enhancer.setCallback(new CglibDbQueryInterceptor());
		// 指定实现的接口
		enhancer.setInterfaces(new Class[]{IDBQuery.class});
		// 生成代理类的实例
		IDBQuery cglibProxy = (IDBQuery)enhancer.create();
		System.out.println(cglibProxy.request());

		// Javassist 动态代理：代理工厂创建
		ProxyFactory proxyFactory = new ProxyFactory();
		// 指定实现的接口
		proxyFactory.setInterfaces(new Class[]{IDBQuery.class});
		Class proxyClass = proxyFactory.createClass();
		IDBQuery javassistProxy = (IDBQuery)proxyClass.newInstance();
		// 指定Handler处理器
		((ProxyObject) javassistProxy).setHandler(new JavassistDbQueryHandler());
		System.out.println(javassistProxy.request());

		// Javassist 动态代理：动态代码创建
		ClassPool mpool = new ClassPool(true);
		// 定义类名
		CtClass mCtc = mpool.makeClass(IDBQuery.class.getName() + "Javassist-BytecodeProxy");
		// 添加需要实现的接口
		mCtc.addInterface(mpool.get(IDBQuery.class.getName()));
		// 添加构造函数
		mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc));
		// 添加类的字段信息，使用动态Java代码
		mCtc.addField(CtField.make("public " + IDBQuery.class.getName() + " real;", mCtc));
		String dbqueryName = DBQuery.class.getName();
		// 添加方法，使用动态Java代码指定内部逻辑
		mCtc.addMethod(CtNewMethod.make("public String request() { if (real == null) real = new " + dbqueryName + "();return real.request(); }", mCtc));
		// 基于以上信息，生成动态类
		Class pc = mCtc.toClass();
		// 生成动态类的实例
		IDBQuery bytecodeProxy = (IDBQuery) pc.newInstance();
		System.out.println(bytecodeProxy.request());
	}
}